﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MashGen.Engine.Expressions.Formatter
{
    public sealed class StringFormatter : AbstractFormatter<Tuple<bool, StringBuilder>>
    {
        static StringFormatter() { }

        private static StringFormatter instance = new StringFormatter();

        private StringFormatter() { }

        public static string Format(AbstractExpression expression, bool insertSpaces)
        {
            var builder = new StringBuilder();
            expression.Vist(instance, new Tuple<bool, StringBuilder>(insertSpaces, builder));
            return builder.ToString();
        }

        protected override void PrintNumber(uint value, Tuple<bool, StringBuilder> parameters)
        {
            parameters.Item2.Append(value);
        }

        protected override void PrintVariable(string name, Tuple<bool, StringBuilder> parameters)
        {
            parameters.Item2.Append(name);
        }

        protected override void PrintOperator(Operator op, Tuple<bool, StringBuilder> parameters)
        {
            switch (op)
            {
                case Operator.Plus:
                    if (parameters.Item1)
                    {
                        parameters.Item2.Append(" + ");
                    }
                    else
                    {
                        parameters.Item2.Append('+');
                    }
                    break;
                case Operator.UnaryMinus:
                    parameters.Item2.Append('-');
                    break;
                case Operator.BinaryMinus:
                    if (parameters.Item1)
                    {
                        parameters.Item2.Append(" - ");
                    }
                    else
                    {
                        parameters.Item2.Append('-');
                    }
                    break;
                case Operator.WeakDot:
                    if (parameters.Item1)
                    {
                        parameters.Item2.Append(' ');
                    }
                    else
                    {
                        parameters.Item2.Append('*');
                    }
                    break;
                case Operator.StrongDot:
                    if (parameters.Item1)
                    {
                        parameters.Item2.Append(" * ");
                    }
                    else
                    {
                        parameters.Item2.Append('*');
                    }
                    break;
            }
        }

        protected override void OpenParenthesis(Tuple<bool, StringBuilder> parameters)
        {
            parameters.Item2.Append('(');
        }

        protected override void CloseParenthesis(Tuple<bool, StringBuilder> parameters)
        {
            parameters.Item2.Append(')');
        }

        protected override void OpenQuotient(Tuple<bool, StringBuilder> parameters)
        {
        }

        protected override void OpenNumerator(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (needsParenthesis)
            {
                parameters.Item2.Append('(');
            }
        }

        protected override void CloseNumerator(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (needsParenthesis)
            {
                parameters.Item2.Append(')');
            }
        }

        protected override void OpenDenominator(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (parameters.Item1)
            {
                parameters.Item2.Append(" / ");
            }
            else
            {
                parameters.Item2.Append('/');
            }
            if (needsParenthesis)
            {
                parameters.Item2.Append('(');
            }
        }

        protected override void CloseDenominator(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (needsParenthesis)
            {
                parameters.Item2.Append(')');
            }
        }

        protected override void CloseQuotient(Tuple<bool, StringBuilder> parameters)
        {
        }

        protected override void OpenPower(Tuple<bool, StringBuilder> parameters)
        {
        }

        protected override void OpenRadix(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (needsParenthesis)
            {
                parameters.Item2.Append('(');
            }
        }

        protected override void CloseRadix(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (needsParenthesis)
            {
                parameters.Item2.Append(')');
            }
        }

        protected override void OpenExponent(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (parameters.Item1)
            {
                parameters.Item2.Append(" ^ ");
            }
            else
            {
                parameters.Item2.Append('^');
            }
            if (needsParenthesis)
            {
                parameters.Item2.Append('(');
            }
        }

        protected override void CloseExponent(Tuple<bool, StringBuilder> parameters, bool needsParenthesis)
        {
            if (needsParenthesis)
            {
                parameters.Item2.Append(')');
            }
        }

        protected override void ClosePower(Tuple<bool, StringBuilder> parameters)
        {
        }
    }
}
